package ide.ccf.ccdesigner;

import java.io.IOException;
import java.net.URL;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.util.ILogger;
import org.eclipse.jface.util.Policy;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

import ide.ccf.ccdesigner.views.embedded.DesignerBridgeW;

/**
 * 设计器插件类
 *
 */
public class DesignerPlugin extends AbstractUIPlugin 
{
    private static DesignerPlugin plugin;	// 共享实例
    private ResourceBundle resourceBundle;
    private DesignerBridgeW designer;
    private static final String BUNDLESYMBOLICNAME = "ide.ccf.ccdesigner";
    private static final String PLUGINSSYMBOLICNAME = "ide.ccf.ccdesignerplugins" + "." + Platform.getOS() + "." + Platform.getOSArch();

    /**
     * 构造器
     */
    public DesignerPlugin() 
    {
        super();
        
        plugin = this;
        
        try 
        {
            resourceBundle = ResourceBundle.getBundle("ide.ccf.ccdesigner.DesignerPluginResources");
        } 
        catch (MissingResourceException x) 
        {
            resourceBundle = null;
        }

    }

    /**
     * 启动，插件激活时调用。
     */
    public void start(BundleContext context) throws Exception 
    {
        super.start(context);

        Display.getDefault().asyncExec(new Runnable() 
        {
            public void run() 
            {
                Shell shell = new Shell();
                designer = new DesignerBridgeW(shell, SWT.EMBEDDED);
                loadPlugins();
            }
        });
    }

    /**
     * 结束，插件关闭时调用。
     */
    public void stop(BundleContext context) throws Exception 
    {
        super.stop(context);
    }

    /**
     * 返回插件实例
     * @return
     */
    public static DesignerPlugin getDefault() {
        return plugin;
    }

    /**
     * 返回插件资源Bundle的字符串，如果为空则返回'key'
     * @param key
     * @return
     */
    public static String getResourceString(String key) 
    {
        ResourceBundle bundle = DesignerPlugin.getDefault().getResourceBundle();
        try 
        {
            return (bundle != null) ? bundle.getString(key) : key;
        } 
        catch (MissingResourceException e) 
        {
            return key;
        }
    }

    /**
     * 返回插件资源Bundle
     * @return
     */
    public ResourceBundle getResourceBundle() {
        return resourceBundle;
    }

    /**
     * 通过插件资源Bundle获取插件路径
     * @return
     * @throws IOException
     */
    protected static String getPluginsPathByBundle() throws IOException
    {
        Bundle pluginBundle = Platform.getBundle(PLUGINSSYMBOLICNAME);
        URL pluginURL = FileLocator.find(pluginBundle, new Path(""), null);
        IPath pluginIPath = new Path(FileLocator.toFileURL(pluginURL).getPath());
        return pluginIPath.toOSString();
    }

    /**
     * 通过安装路径获取插件路径
     * @return
     */
    protected static String getPluginsPathByInstallLocation()
    {
        IPath installLocationPath = new Path(Platform.getInstallLocation().getURL().getPath());
        installLocationPath = installLocationPath.append("plugins");
        installLocationPath = installLocationPath.append(PLUGINSSYMBOLICNAME);
        String pluginPath = installLocationPath.toOSString();
        return pluginPath;
    }

    /**
     * 不存在某些必需的动态库时的出错信息
     * 为了实现插件，使用了一些运行时库，这些库不应该被认为是非法插件，所以需要忽略
     * @param error
     * @return
     */
    protected static String getErrorStringWithoutShippedDlls(String error)
    {
        String result = error;
        if (Platform.getOS().equals(Platform.OS_WIN32)) 
        {
            result = "";
            String[] errors = error.split("\n");
            String[] dllsToIgnore = {"Qt3Support", "QtNetwork", "QtSql"};
            for (int i = 0; i < errors.length; i++) 
            {
                boolean dllsToIgnoreInError = false;

                for (int j = 0; j < dllsToIgnore.length; j++) 
                {
                    if (errors[i].indexOf(dllsToIgnore[j]) > -1) 
                    {
                        dllsToIgnoreInError = true;
                        break;
                    }
                }

                if (!dllsToIgnoreInError) 
                {
                    if (result.length() > 0)
                        result += '\n';
                    
                    result += errors[i];
                }
            }
        }
        return result;
    }

    /**
     * 装载插件
     */
    public void loadPlugins()
    {
        String pluginPath = null;
        try 
        {
            try 
            {
                pluginPath = getPluginsPathByBundle();
            } 
            catch (IOException e1) 
            {
                pluginPath = getPluginsPathByInstallLocation();
            }
            designer.setPluginPath(pluginPath);
            String failure = getErrorStringWithoutShippedDlls(designer.pluginFailureString());

            if (failure.length() != 0) 
            {
                ILogger logger = Policy.getLog();
                logger.log(new Status(Status.WARNING, BUNDLESYMBOLICNAME, Status.WARNING, "某些窗体编辑器插件无法装载。", new Exception(failure)));
            }
        } 
        catch (Exception e2) 
        {
            //
        }
    }
}
